home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Snippets / QuickDraw / SeedCFill Example / Source / SeedCFill Example.c
Encoding:
C/C++ Source or Header  |  1996-09-17  |  7.7 KB  |  270 lines  |  [TEXT/CWIE]

  1. /****************************************************************************/
  2. /*                                                                            */
  3. /*    Application:    SeedCFill Example                                        */
  4. /*                                                                            */
  5. /*    Description:    This snippet shows how to use the SeedCFill routine        */
  6. /*                    to create a mask given a source image. As decribed        */
  7. /*                    on page 71 of Inside Mac volume V, this routine            */
  8. /*                    computes a destination bitmap image with 1's only        */
  9. /*                    in the pixels where paint can not leak from the            */
  10. /*                    starting seed point. This is similar to the paint-        */
  11. /*                    bucket tool.                                            */
  12. /*                                                                            */
  13. /*    File:            SeedCFill Example.π                                        */
  14. /*                    SeedCFill Example.c                                        */
  15. /*                    SeedCFill Example.π.rsrc                                */
  16. /*                                                                            */
  17. /*    Programmer:        Edgar Lee                                                */
  18. /*    Organization:    Apple Computer, Inc.                                    */
  19. /*    Department:        Developer Technical Support, DTS                        */
  20. /*    Language:        C (Think C version 5.0.2)                                */
  21. /*    Date Created:    10-19-92                                                */
  22. /*                                                                            */
  23. /****************************************************************************/
  24.  
  25. #include <Dialogs.h>
  26. #include <Fonts.h>
  27. #include <Palettes.h>
  28. #include <QDOffscreen.h>
  29. #include <Resources.h>
  30.  
  31. /* Constant Declarations */
  32.  
  33. #define    WWIDTH        (176 * 2)
  34. #define    WHEIGHT        (106 * 2)
  35.  
  36. #define WLEFT        (((qd.screenBits.bounds.right - qd.screenBits.bounds.left) - WWIDTH) / 2)
  37. #define WTOP        (((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - WHEIGHT) / 2)
  38.  
  39. /* Global Variable Definitions */
  40.  
  41. WindowPtr    gWindow;
  42.  
  43. void initMac();
  44. void createWindow();
  45. void doSeedCFillExample();
  46.  
  47. void DisposeGrafPort();
  48. GrafPtr CreateGrafPort();
  49.  
  50. void doEventLoop();
  51.  
  52. void main(void)
  53. {
  54.     initMac();
  55.     createWindow();
  56.     doEventLoop();
  57. }
  58.  
  59. void initMac()
  60. {
  61.     MaxApplZone();
  62.     
  63.     InitGraf( &qd.thePort );
  64.     InitFonts();
  65.     InitWindows();
  66.     InitMenus();
  67.     TEInit();
  68.     InitDialogs( nil );
  69.     InitCursor();
  70.     FlushEvents( 0, everyEvent );
  71. }
  72.  
  73. void createWindow()
  74. {
  75.     Rect            rect;
  76.     PaletteHandle    palette;
  77.     
  78.     SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
  79.     
  80.     gWindow = NewCWindow( 0L, &rect, "\pClick anywhere in left image.", true, documentProc,
  81.                             (WindowPtr)-1L, true, 0L );
  82.                             
  83.     SetPort( gWindow );
  84.  
  85.     /****************************************************************************/    
  86.     /* Attach a palette of the default colortable to the window.                */
  87.     /*  WARNING: SeedCFill may not work if the current gDevice's colortable is     */
  88.     /*    different than that of the offscreen's colortable.  This offscreen is     */
  89.     /*    the one passed into SeedCFill.  To eliminate this problem, we attach a    */
  90.     /*    palette contaning the same colors used by the offscreen to the window.    */
  91.     /****************************************************************************/
  92.     
  93.     palette = NewPalette( 256, GetCTable( 8 ), pmTolerant, 0 );
  94.     SetPalette( gWindow, palette, true );
  95. }
  96.  
  97. void doSeedCFillExample( point )
  98. Point    point;
  99. {
  100.     PicHandle        pict;                /* Pict used for the source. */
  101.     GWorldPtr        source;                /* Gworld used to store the pict. */
  102.     PixMapHandle    sourcePixMap;        /* Handle to the source Gworld. */
  103.     GrafPtr            mask;                /* BitMap used for creating the mask. */
  104.     int                seedH, seedV;        /* Pixel position used to determine the mask. */
  105.     Rect            rect;                /* Bounding rect of mask and source. */
  106.     CGrafPtr        currentPort;        /* Saved CGrafPtr for later restore. */
  107.     GDHandle        currentDevice;        /* Saved device for later restore. */
  108.     
  109.     /* Load the pict resource to be used for the source. */
  110.     pict = (PicHandle)GetResource( 'PICT', 128 );
  111.  
  112.     /* Define the bounding rect for the source and mask. */
  113.     rect = (**pict).picFrame;
  114.     OffsetRect( &rect, -rect.left, -rect.top );
  115.     rect.right *= 2;
  116.     rect.bottom *= 2;
  117.     
  118.     /* Draw the source image in the window to see what the mask will be created from. */
  119.     DrawPicture( pict, &rect );
  120.     HPurge( (Handle)pict );
  121.     
  122.     /* Return if mouse click was not within the source rect. */
  123.     if (point.h < rect.left || point.h > rect.right ||
  124.         point.v < rect.top || point.v > rect.bottom)
  125.             return;
  126.  
  127.     /* Create a gworld to store the pict. */
  128.     NewGWorld( &source, 8, &rect, GetCTable( 8 ), nil, 0 );
  129.     sourcePixMap = GetGWorldPixMap( source );
  130.     
  131.     /* Draw the pict into the gworld. */
  132.     GetGWorld( ¤tPort, ¤tDevice );
  133.     SetGWorld( source, nil );
  134.     DrawPicture( pict, &rect );
  135.     SetGWorld( currentPort, currentDevice );
  136.         
  137.     /* Allocate a bitmap for the mask. */
  138.     mask = CreateGrafPort( &(**sourcePixMap).bounds );
  139.  
  140.     /* Use the mouse click as the starting seed position. */
  141.     seedH = point.h;
  142.     seedV = point.v;
  143.     
  144.     /* Create a mask from the source, starting from the seed point. */
  145.     SeedCFill( (BitMap *)*sourcePixMap, &(*mask).portBits, &(**sourcePixMap).bounds,
  146.                 &(*mask).portRect, seedH, seedV, nil, 0 );
  147.         
  148.     /* Draw a red cross where the mouse was last clicked. */
  149.     ForeColor( redColor );
  150.     MoveTo( rect.left + seedH - 2, seedV );
  151.     LineTo( rect.left + seedH + 2, seedV );
  152.     MoveTo( rect.left + seedH, seedV - 2 );
  153.     LineTo( rect.left + seedH, seedV + 2 );
  154.     ForeColor( blackColor );
  155.     
  156.     OffsetRect( &rect, (**sourcePixMap).bounds.right, 0 );
  157.     EraseRect( &rect );
  158.     
  159.     /* Copy the source to the window while applying the mask. */
  160.     CopyMask( (BitMap *)*sourcePixMap, &((GrafPtr)mask)->portBits, &gWindow->portBits,
  161.                 &(**sourcePixMap).bounds, &((GrafPtr)mask)->portRect, &rect );
  162.     
  163.     /* Release the used memory. */
  164.     DisposeGrafPort( (GrafPtr)mask );
  165.     DisposeGWorld( source );
  166. }
  167.  
  168. GrafPtr CreateGrafPort( bounds )    /* CreateGrafPort originally written by Forrest Tanaka. */
  169. Rect *bounds;
  170. {
  171.     GrafPtr    savedPort;        /* Saved GrafPtr for later restore. */
  172.     GrafPtr    newPort;        /* New GrafPort. */
  173.     Rect    localBounds;    /* Local copy of bounds. */
  174.  
  175.     GetPort( &savedPort );
  176.  
  177.     /* Set the top-left corner of bounds to (0,0). */
  178.     localBounds = *bounds;
  179.     OffsetRect( &localBounds, -bounds->left, -bounds->top );
  180.  
  181.     /* Allocate a new GrafPort. */
  182.     newPort = (GrafPtr)NewPtrClear( sizeof( GrafPort ) );
  183.     
  184.     if (newPort != nil)
  185.     {
  186.         /* Initialize the new port and make the current port. */
  187.         OpenPort( newPort );
  188.  
  189.         /* Initialize and allocate the bitmap. */
  190.         newPort->portBits.bounds = localBounds;
  191.           newPort->portBits.rowBytes = ((localBounds.right + 15) >> 4) << 1;
  192.         newPort->portBits.baseAddr =  NewPtrClear( newPort->portBits.rowBytes *
  193.                                                     (long)localBounds.bottom );
  194.         if (newPort->portBits.baseAddr != nil)
  195.         {
  196.             /* Clean up the new port. */
  197.             newPort->portRect = localBounds;
  198.             ClipRect( &localBounds );
  199.             RectRgn( newPort->visRgn, &localBounds );
  200.             EraseRect( &localBounds );
  201.         }
  202.         else
  203.         {
  204.             /* Allocation failed; deallocate the port. */
  205.             ClosePort( newPort );
  206.             DisposePtr( (Ptr)newPort );
  207.             newPort = nil;
  208.         }
  209.     }
  210.     
  211.     SetPort( savedPort );
  212.     return newPort;
  213. }
  214.  
  215. void DisposeGrafPort( doomedPort )    /* DisposeGrafPort originally written by Forrest Tanaka. */
  216. GrafPtr doomedPort;
  217. {
  218.     ClosePort( doomedPort );
  219.     DisposePtr( doomedPort->portBits.baseAddr );
  220.     DisposePtr( (Ptr)doomedPort );
  221. }
  222.  
  223. void doEventLoop()
  224. {
  225.     EventRecord        event;
  226.     WindowPtr        window;
  227.     short            clickArea;
  228.     Rect              screenRect;
  229.     static Point    point = { -1, -1 };
  230.     
  231.     for (;;)
  232.     {
  233.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  234.         {
  235.             if (event.what == mouseDown)
  236.             {
  237.                 clickArea = FindWindow( event.where, &window );
  238.                 
  239.                 if (clickArea == inDrag)
  240.                 {
  241.                     screenRect = (**GetGrayRgn()).rgnBBox;
  242.                     DragWindow( window, event.where, &screenRect );
  243.                 }
  244.                 else if (clickArea == inContent)
  245.                 {
  246.                     if (window != FrontWindow())
  247.                         SelectWindow( window );
  248.                     else
  249.                     {
  250.                         point = event.where;
  251.                         GlobalToLocal( &point );
  252.                         doSeedCFillExample( point );
  253.                     }
  254.                 }
  255.                 else if (clickArea == inGoAway)
  256.                     if (TrackGoAway( window, event.where ))
  257.                         return;
  258.             }
  259.             else if (event.what == updateEvt)
  260.             {
  261.                 window = (WindowPtr)event.message;    
  262.                 SetPort( window );
  263.                 
  264.                 BeginUpdate( window );
  265.                 doSeedCFillExample( point );
  266.                 EndUpdate( window );
  267.             }
  268.         }
  269.     }
  270. }